home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xarchie-2.0.9 / ftp-actions.c < prev    next >
C/C++ Source or Header  |  1995-06-18  |  13KB  |  498 lines

  1. /*
  2.  * ftp-actions.c : X/FTP interface routines for xarchie
  3.  *
  4.  * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
  5.  * 13 May 1993: Check for NULL return from ftpNewContext().
  6.  * 27 Jul 1993: Don't use boolean AND of condition flags for XtAppAddInput().
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <fcntl.h>            /* O_RDONLY, etc. */
  11. #include <X11/Intrinsic.h>
  12. #include <X11/Shell.h>
  13. #include <X11/StringDefs.h>
  14. #include <X11/Xaw/Form.h>
  15. #include <X11/Xaw/Command.h>
  16. #include <X11/Xaw/AsciiText.h>
  17. #include <X11/Xaw/Dialog.h>
  18. #include "config.h"
  19. #ifdef HAVE_SYS_PARAM_H
  20. #include <sys/param.h>
  21. #endif
  22. #include "db.h"
  23. #include "appres.h"
  24. #include "xarchie.h"
  25. #include "selection.h"
  26. #include "browser.h"
  27. #include "ftp.h"
  28. #include "view-file.h"
  29. #include "status.h"
  30. #include "popups.h"
  31. #include "xutil.h"
  32. #include "alert.h"
  33. #include "syserr.h"
  34. #include "debug.h"
  35.  
  36. /*
  37.  * Functions defined here
  38.  */
  39. void initFtpActions();
  40. void ftpGetSelectedItems(),ftpOpenSelectedItems();
  41. void RegisterFtpFd(),UnregisterFtpFd();
  42. int ftpPrompt();
  43.  
  44. static void ftpSelectedItems(),countFileToGet(),countFileToOpen(),addFile();
  45. static void ftpGetFinished(),ftpOpenOneFinished();
  46. static void initFtpTraceWidgets();
  47. static void ftpTraceDoneAction();
  48. static void ftpTraceReset(),ftpTraceFunc();
  49. static void inputCallback();
  50. static void ftpPromptCallback();
  51.  
  52. /*
  53.  * Data defined here
  54.  */
  55. static char **ftpFilenames;
  56. static int numFtpFiles;
  57. static FtpContext *ftpCurrentContext;
  58.  
  59. static Widget ftpTraceShell,ftpTraceText;
  60. static Boolean isPoppedUp;
  61.  
  62. static XtActionsRec actionTable[] = {
  63.     { "ftp-trace-done",    ftpTraceDoneAction },
  64. };
  65.  
  66. /*    -    -    -    -    -    -    -    -    */
  67. /* Interface functions */
  68.  
  69. void
  70. initFtpActions()
  71. {
  72.     XtAppAddActions(appContext,actionTable,XtNumber(actionTable));
  73. }
  74.  
  75. void
  76. ftpGetSelectedItems()        /* Called from getAction() */
  77. {
  78.     ftpSelectedItems(appResources.ftpLocalDir,appResources.ftpType,
  79.              appResources.ftpPrompt,appResources.ftpStrip,
  80.              countFileToGet,NULL,ftpGetFinished);
  81. }
  82.  
  83. void
  84. ftpOpenSelectedItems()        /* Called from openBrowser() */
  85. {
  86.     ftpSelectedItems(tmpDirectory,"ascii",False,True,
  87.              countFileToOpen,ftpOpenOneFinished,ftpGetFinished);
  88. }
  89.  
  90. void
  91. ftpAbortTransfer()
  92. {
  93.     DEBUG1("ftpAbortTransfer: ftpCurrentContext=0x%x\n",ftpCurrentContext);
  94.     ftpAbort(ftpCurrentContext);
  95.     DEBUG0("ftpAbortTransfer: done\n");
  96. }
  97.  
  98. /*    -    -    -    -    -    -    -    -    */
  99. /*
  100.  * This function starts ftp retrieval of the items selected in the
  101.  * browser into the local directory.
  102.  */
  103. static void
  104. ftpSelectedItems(local_dir,typestr,prompt,strip,
  105.          countProc,doneOneProc,doneAllProc)
  106. char *local_dir,*typestr;
  107. Boolean prompt,strip;
  108. void (*countProc)();
  109. FtpCallbackProc doneOneProc,doneAllProc;
  110. {
  111.     char *host,*cwd;
  112.     int type;
  113. #ifdef DEBUG
  114.     int i;
  115. #endif
  116.  
  117.     DEBUG0("ftpSelectedItems: setting files to transfer\n");
  118.     numFtpFiles = 0;
  119.     forEachSelectedItem(countProc);
  120.     if (numFtpFiles == 0) {
  121.     return;
  122.     }
  123.     ftpFilenames = (char **)XtCalloc(numFtpFiles,sizeof(char *));
  124.     numFtpFiles = 0;
  125.     forEachSelectedItem(addFile);
  126. #ifdef DEBUG
  127.     for (i=0; i < numFtpFiles; i++)
  128.     fprintf(stderr,"ftpSelectedItems: ftpFilenames[%d] = \"%s\"\n",
  129.         i,ftpFilenames[i]);
  130. #endif
  131.     /* Is there a host? */
  132.     if ((host=getWidgetString(hostText)) == NULL || *host == '\0') {
  133.     alert0("No host specified for transfer!");
  134.     return;
  135.     }
  136.     DEBUG1("ftpSelectedItems: host = \"%s\"\n",host);
  137.     /* Optional remote directory */
  138.     cwd = getWidgetString(locationText); /* Can be "" */
  139.     DEBUG1("ftpSelectedItems: remote dir = \"%s\"\n",cwd);
  140.     if (cwd && *cwd == '\0')
  141.     cwd = NULL;
  142.     /* Convert type to ARPA code */
  143.     if (typestr == NULL || *typestr == 'a' || *typestr == 'A')
  144.     type = TYPE_A;
  145.     else if (*typestr == 'b' || *typestr == 'B')
  146.     type = TYPE_I;
  147.     else if (*typestr == 'e' || *typestr == 'E')
  148.     type = TYPE_E;
  149.     else
  150.     type = atoi(typestr);
  151.     /* Put up the tracing window if needed */
  152.     if (appResources.ftpTrace) {
  153.     if (ftpTraceShell == NULL)
  154.         initFtpTraceWidgets();
  155.     ftpTraceReset();
  156.     isPoppedUp = True;
  157.     XtPopup(ftpTraceShell,XtGrabNone);
  158.     }
  159.     /* Get the FTP context */
  160.     ftpCurrentContext =
  161.     ftpNewContext(host,"anonymous",appResources.ftpMailAddress,
  162.               cwd,local_dir,type,strip,(numFtpFiles>1 && prompt),
  163.               FTP_GET,ftpFilenames,numFtpFiles,
  164.               (appResources.ftpTrace ? ftpTraceFunc : NULL),
  165.               doneOneProc,doneAllProc);
  166.     XtFree((char *)ftpFilenames);
  167.     /* Hostname lookup might have failed */
  168.     if (ftpCurrentContext == NULL)
  169.     return;
  170.     /* Here we go... */
  171.     setBrowserState(BROWSER_FTP);
  172.     ftpStart(ftpCurrentContext);
  173.     DEBUG0("ftpSelectedItems: done\n");
  174. }
  175.  
  176. /*    -    -    -    -    -    -    -    -    */
  177. /* Functions called by ftpGetSelectedItems */
  178.  
  179. /*ARGSUSED*/
  180. static void
  181. countFileToGet(dbp,list_index)        /* complains about non-files */
  182. DbEntry *dbp;
  183. int list_index;
  184. {
  185.     if (dbp->type == DB_FILE) {
  186.     numFtpFiles += 1;
  187.     } else {
  188.     alert1("Can't retrieve non-file \"%s\".",dbp->name);
  189.     }
  190. }
  191.  
  192. /*ARGSUSED*/
  193. static void
  194. countFileToOpen(dbp,list_index)        /* doesn't complain about non-files */
  195. DbEntry *dbp;
  196. int list_index;
  197. {
  198.     if (dbp->type == DB_FILE) {
  199.     numFtpFiles += 1;
  200.     }
  201. }
  202.  
  203. /*ARGSUSED*/
  204. static void
  205. addFile(dbp,list_index)            /* adds filename to array */
  206. DbEntry *dbp;
  207. int list_index;
  208. {
  209.     if (dbp->type == DB_FILE) {
  210.     ftpFilenames[numFtpFiles++] = XtNewString(dbp->name);
  211.     }
  212. }
  213.  
  214. /*    -    -    -    -    -    -    -    -    */
  215. /* FTP callbacks */
  216.  
  217. /*
  218.  * This function is called back when the ftp transfer is complete (for
  219.  * whatever reason).
  220.  */
  221. /*ARGUSED*/
  222. static void
  223. ftpGetFinished(ftpc)
  224. FtpContext *ftpc;
  225. {
  226.     DEBUG1("ftpGetFinished(0x%x)...\n",ftpc);
  227.     setBrowserState(BROWSER_READY);
  228.     ftpFreeContext(ftpc);
  229.     status0("Ready");
  230.     DEBUG0("ftpGetFinished: done\n");
  231. }
  232.  
  233. /*
  234.  * This function is called back when a single file has been successfully
  235.  * retrieved for Open.
  236.  */
  237. /*ARGSUSED*/
  238. static void
  239. ftpOpenOneFinished(ftpc)
  240. FtpContext *ftpc;
  241. {
  242.     char filename[MAXPATHLEN];
  243.  
  244.     DEBUG1("ftpOpenOneFinished(0x%x)...\n",ftpc);
  245.     if (ftpc->local_dir && *(ftpc->local_dir))
  246.     sprintf(filename,"%s/%s",ftpc->local_dir,ftpc->files[ftpc->this_file]);
  247.     else
  248.     strcpy(filename,ftpc->files[ftpc->this_file]);
  249.     viewFile(filename);
  250.     DEBUG0("ftpOpenOneFinished: done\n");
  251. }
  252.  
  253. /*    -    -    -    -    -    -    -    -    */
  254. /* Routines for tracing the ftp connection in a window */
  255.  
  256. static void
  257. initFtpTraceWidgets()
  258. {
  259.     Widget form;
  260.  
  261.     ftpTraceShell = XtCreatePopupShell("ftpTraceShell",
  262.                        topLevelShellWidgetClass,
  263.                        toplevel,NULL,0);
  264.     form = XtCreateManagedWidget("ftpTraceForm",formWidgetClass,
  265.                  ftpTraceShell,NULL,0);
  266.     (void)XtCreateManagedWidget("ftpTraceDismissButton",commandWidgetClass,
  267.                 form,NULL,0);
  268.     ftpTraceText = XtCreateManagedWidget("ftpTraceText",asciiTextWidgetClass,
  269.                      form,NULL,0);
  270.     XtRealizeWidget(ftpTraceShell);
  271.     (void)XSetWMProtocols(XtDisplay(ftpTraceShell),XtWindow(ftpTraceShell),
  272.               &WM_DELETE_WINDOW,1);
  273. }
  274.  
  275. void
  276. setFtpTraceShellState(state)
  277. int state;
  278. {
  279.     if (!isPoppedUp)
  280.     return;
  281.     switch (state) {
  282.     case NormalState:
  283.         XtMapWidget(ftpTraceShell);
  284.         break;
  285.     case IconicState:
  286.         XtUnmapWidget(ftpTraceShell);
  287.         break;
  288.     }
  289. }
  290.  
  291. /*ARGSUSED*/
  292. static void
  293. ftpTraceDoneAction(w,event,params,num_params)
  294. Widget w;
  295. XEvent *event;
  296. String *params;
  297. Cardinal *num_params;
  298. {
  299.     isPoppedUp = False;
  300.     XtPopdown(ftpTraceShell);
  301. }
  302.  
  303. static void
  304. ftpTraceReset()
  305. {
  306.     Arg args[1];
  307.  
  308.     XtSetArg(args[0],XtNstring,"");
  309.     XtSetValues(ftpTraceText,args,1);
  310. }
  311.  
  312. /*
  313.  * This function is called back from within the ftp routines to monitor
  314.  * the exchange of messages.
  315.  */
  316. /*ARGSUSED*/
  317. static void
  318. ftpTraceFunc(ftpc,who,text)
  319. FtpContext *ftpc;
  320. int who;        /* 0 => recvd, non-0 => sent */
  321. char *text;        /* text of this message */
  322. {
  323.     if (who)
  324.     appendWidgetText(ftpTraceText,"ftp> ");
  325.     appendWidgetText(ftpTraceText,text);
  326.     if (*(text+strlen(text)-1) != '\n')
  327.     appendWidgetText(ftpTraceText,"\n");
  328. }
  329.  
  330. /*    -    -    -    -    -    -    -    -    */
  331. /* File descriptor registration routines: */
  332.  
  333. /*
  334.  * We need as many of these as there are file descriptors. It's
  335.  * easier to guess big than to figure out where such a magic number lives.
  336.  */
  337. #define NUMFDS 64
  338.  
  339. struct _ftpRegisteredFds_struct {
  340.     FtpCallbackProc proc;
  341.     FtpContext *context;
  342.     XtInputId readid,writeid;
  343. } ftpRegisteredFds[NUMFDS];
  344.  
  345. /*
  346.  * This function is exported and used by the FTP routines to register
  347.  * a file descriptor for notification. We register it by recording the
  348.  * callback information (proc and ftpc) and telling X to register the
  349.  * fd as an external input source. When X calls back to inputCallback(),
  350.  * we use the stored information to call back to the FTP routine.
  351.  * Got that?
  352.  */
  353. void
  354. RegisterFtpFd(ftpc,fd,flags,proc)
  355. FtpContext *ftpc;
  356. int fd,flags;
  357. FtpCallbackProc proc;
  358. {
  359.     DEBUG3("RegisterFtpFd: ftpc=0x%x, fd=%d, flags=%d\n",ftpc,fd,flags);
  360.     if (fd < 0 || fd >= NUMFDS) {
  361.     fprintf(stderr,"YOW! Attempt to register fd %d!\n",fd);
  362. #ifdef DEBUG
  363.     abort();
  364. #endif
  365.     return;
  366.     }
  367.     ftpRegisteredFds[fd].proc = proc;
  368.     ftpRegisteredFds[fd].context = ftpc;
  369.     /*
  370.      * In R4, we can't give a boolean combination of flags to XtAppAddInput().
  371.      * Even if it doesn't complain, XtRemoveInput() won't remove the fd from
  372.      * both select() masks, so we'll get the "select failed" message.
  373.      */
  374.     switch (flags) {
  375.       case O_RDONLY:
  376.     ftpRegisteredFds[fd].readid =
  377.         XtAppAddInput(appContext,fd,(XtPointer)XtInputReadMask,
  378.               inputCallback,NULL);
  379.     ftpRegisteredFds[fd].writeid = (XtInputId)NULL;
  380.     break;
  381.       case O_WRONLY:
  382.     ftpRegisteredFds[fd].readid = (XtInputId)NULL;
  383.     ftpRegisteredFds[fd].writeid =
  384.         XtAppAddInput(appContext,fd,(XtPointer)XtInputWriteMask,
  385.               inputCallback,NULL);
  386.     break;
  387.       case O_RDWR:
  388.     ftpRegisteredFds[fd].readid =
  389.         XtAppAddInput(appContext,fd,(XtPointer)XtInputReadMask,
  390.               inputCallback,NULL);
  391.     ftpRegisteredFds[fd].writeid =
  392.         XtAppAddInput(appContext,fd,(XtPointer)XtInputWriteMask,
  393.               inputCallback,NULL);
  394.     break;
  395.     }
  396.     DEBUG2("RegisterFtpFd: done: readid=0x%x, writeid=0x%x\n",
  397.        ftpRegisteredFds[fd].readid,ftpRegisteredFds[fd].writeid);
  398. }
  399.  
  400. /*
  401.  * Called back when X says source is ready. We call the function registered
  402.  * by the FTP routines, passing the context.
  403.  */
  404. /*ARGSUSED*/
  405. static void
  406. inputCallback(client_data,source,id)
  407. XtPointer client_data;
  408. int *source;
  409. XtInputId *id;
  410. {
  411.     if (ftpRegisteredFds[*source].proc != NULL) {
  412.     (*(ftpRegisteredFds[*source].proc))(ftpRegisteredFds[*source].context);
  413.     } else {
  414.     fprintf(stderr,"YOW! Callback for fd=%d not registered!\n",*source);
  415. #ifdef DEBUG
  416.     abort();
  417. #endif
  418.     }
  419. }
  420.  
  421. /*
  422.  * This function is exported and used by the FTP routines to undo
  423.  * a previous registration.
  424.  */
  425. /*ARGSUSED*/
  426. void
  427. UnregisterFtpFd(ftpc,fd)
  428. FtpContext *ftpc;
  429. int fd;
  430. {
  431.     DEBUG2("UnregisterFtpFd: ftpc=0x%x, fd=%d\n",ftpc,fd);
  432.     if (fd < 0 || fd >= NUMFDS) {
  433.     fprintf(stderr,"YOW! Attempt to unregister fd %d!\n",fd);
  434. #ifdef DEBUG
  435.     abort();
  436. #endif
  437.     return;
  438.     }
  439.     DEBUG2("UnregisterFtpFd: readid=0x%x, writeid=0x%x\n",
  440.        ftpRegisteredFds[fd].readid,ftpRegisteredFds[fd].writeid);
  441.     if (ftpRegisteredFds[fd].readid != (XtInputId)NULL)
  442.     XtRemoveInput(ftpRegisteredFds[fd].readid);
  443.     ftpRegisteredFds[fd].readid = (XtInputId)NULL;
  444.     if (ftpRegisteredFds[fd].writeid != (XtInputId)NULL)
  445.     XtRemoveInput(ftpRegisteredFds[fd].writeid);
  446.     ftpRegisteredFds[fd].writeid = (XtInputId)NULL;
  447.     ftpRegisteredFds[fd].proc = NULL;
  448.     ftpRegisteredFds[fd].context = NULL;
  449.     DEBUG0("UnregisterFtpFd: done\n");
  450. }
  451.  
  452. /*    -    -    -    -    -    -    -    -    */
  453. /* Routines for prompting during FTP transfers: */
  454.  
  455. static Widget ftpPromptShell;
  456. static int ftpPromptResult;
  457.  
  458. int
  459. ftpPrompt(ftpc)
  460. FtpContext *ftpc;
  461. {
  462.     char str[256];
  463.  
  464.     if (ftpPromptShell == NULL)
  465.     ftpPromptShell = createPopup("ftpPrompt",4,ftpPromptCallback);
  466.     sprintf(str,"%s %s?",
  467.         (ftpc->filecmd==FTP_GET?"GET":"PUT"),ftpc->files[ftpc->this_file]);
  468.     setPopupLabel(ftpPromptShell,"ftpPrompt",str);
  469.     popupMainLoop(ftpPromptShell);
  470.     return(ftpPromptResult);
  471. }
  472.  
  473. /*ARGSUSED*/
  474. static void
  475. ftpPromptCallback(w,client_data,call_data)
  476. Widget w;
  477. XtPointer client_data;        /* button number */
  478. XtPointer call_data;
  479. {
  480.     switch ((int)client_data) {
  481.       case 0:            /* Yes */
  482.     ftpPromptResult = 1;
  483.     break;
  484.       case 1:            /* No */
  485.     ftpPromptResult = 0;
  486.     break;
  487.       case 2:            /* All */
  488.     ftpCurrentContext->prompt = 0;
  489.     ftpPromptResult = 1;
  490.     break;
  491.       case 3:            /* Abort */
  492.     ftpCurrentContext->this_file = ftpCurrentContext->num_files;
  493.     ftpPromptResult = 0;
  494.     break;
  495.     }
  496.     popupDone();
  497. }
  498.